package com.leil.movies.spider;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.leil.movies.project.entity.Movie;
import com.leil.movies.project.rest.exception.DouBanApiException;
import com.leil.movies.project.service.impl.MovieServiceImpl;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

import java.util.List;
import java.util.Map;

public class MovieSpiderProcessor {

    private final Logger logger = LoggerFactory.getLogger(MovieSpiderProcessor.class);

    private String baseUrl = "https://movie.douban.com/j/new_search_subjects?sort=U&range=0,10&tags=";

    ThreadLocal<MovieServiceImpl> movieServiceThreadLocal = new ThreadLocal<>();

    RestTemplate restTemplate;

    public MovieSpiderProcessor(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    public void setMovieService(MovieServiceImpl movieService) {
        this.movieServiceThreadLocal.set(movieService);
    }

    public int process(String genres, int start) {
        ResponseEntity<JSONObject> response = null;
        String url = this.baseUrl + "&genres=" + genres + "&start=" + start;
        try {
            response = this.restTemplate.getForEntity(url, JSONObject.class);
        } catch (DouBanApiException e) {
            logger.error("【" + Thread.currentThread().getName() + "】" + "处理URL：" + url + "发生错误：" + e.getMessage());
            this.sleep(100000);
            this.process(genres, start);
        }
        JSONObject res = response.getBody();
        if (ObjectUtils.isNotEmpty(res.get("r")) && Integer.parseInt(res.get("r").toString()) == 1
                && ObjectUtils.isNotEmpty(res.get("msg"))) {
            logger.error("【" + Thread.currentThread().getName() + "】" + "处理URL：" + url + "发生错误：" + response.getBody());
            this.sleep(100000);
            this.process(genres, start);
        }
        // 处理正常逻辑插入数据库
        int count = 20;
        try {
            count = this.save(res, genres);
        } catch (Exception e) {
            logger.error("【" + Thread.currentThread().getName() + "】" + "处理URL：" + url + "发生错误：" + e.getMessage());
        }
        System.out.println("【" + Thread.currentThread().getName() + "】" + "正常执行URL：" + url + response.getBody());
        this.sleep(15000);
        return count;
    }

    private void sleep(int millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private int save(JSONObject json, String genres) {
        List<Object> dataArr = (List<Object>) json.get("data");
        for (Object data : dataArr) {
            Map<String, Object> movieData = (Map<String, Object>) data;
            Movie movie = this.convertToMovie(movieData, genres);
            try {
                this.movieServiceThreadLocal.get().save(movie);
            } catch (DuplicateKeyException e) {
                logger.error("ID【" + movie.getId() + "】电影已经存在");
            } catch (Exception e) {
                logger.error("ID【" + movie.getId() + "】电影未知错误：" + e.getMessage());
            }
        }
        return dataArr.size();
    }


    private Movie convertToMovie(Map<String, Object> movieData, String genres) {
        String id = (String) movieData.get("id");
        String directors = StringUtils.join((List<String>) movieData.get("directors"), ",");
        String rate = (String) movieData.get("rate");
        String star = (String) movieData.get("star");
        String title = (String) movieData.get("title");
        String url = (String) movieData.get("url");
        String casts = StringUtils.join((List<String>) movieData.get("casts"), ",");
        String cover = (String) movieData.get("cover");
        String coverX = movieData.get("cover_x").toString();
        String coverY = movieData.get("cover_y").toString();
        Movie movie = new Movie();
        movie.setId(id);
        movie.setDirectors(directors);
        movie.setRate(rate);
        movie.setStar(star);
        movie.setTitle(title);
        movie.setUrl(url);
        movie.setCasts(casts);
        movie.setCover(cover);
        movie.setCoverX(coverX);
        movie.setCoverY(coverY);
        movie.setGenres(genres);
        return movie;
    }


}
